import { ref, type Ref } from 'vue'
import { Terminal } from '@xterm/xterm'
import { FitAddon } from '@xterm/addon-fit'

// WebSSH连接类型
export type WebSSHConnection = {
  terminal: Terminal | null
  fitAddon: FitAddon | null
  socket: WebSocket | null
  status: 'disconnected' | 'connecting' | 'connected' | 'error'
  dataHandler: ((data: string) => void) | null
  container: HTMLElement | null
  initialized: boolean
  resizeObserver: ResizeObserver | null
}

export type WebSSHServer = { name: string; ip: string; port: number }

// 全局WebSSH连接管理器 - 单例模式
class WebSSHManager {
  private connections = new Map<string, WebSSHConnection>()
  private servers: WebSSHServer[] = []
  
  // 获取或创建连接
  public getConnection(serverIp: string): WebSSHConnection {
    if (!this.connections.has(serverIp)) {
      this.connections.set(serverIp, {
        terminal: null,
        fitAddon: null,
        socket: null,
        status: 'disconnected',
        dataHandler: null,
        container: null,
        initialized: false,
        resizeObserver: null
      })
    }
    return this.connections.get(serverIp)!
  }
  
  // 获取所有连接
  public getAllConnections(): Map<string, WebSSHConnection> {
    return this.connections
  }
  
  // 设置服务器列表
  public setServers(servers: WebSSHServer[]) {
    this.servers = servers
    // 为每个服务器创建连接对象（如果不存在）
    for (const server of servers) {
      if (!this.connections.has(server.ip)) {
        this.connections.set(server.ip, {
          terminal: null,
          fitAddon: null,
          socket: null,
          status: 'disconnected',
          dataHandler: null,
          container: null,
          initialized: false,
          resizeObserver: null
        })
      }
    }
  }
  
  // 获取服务器列表
  public getServers(): WebSSHServer[] {
    return this.servers
  }
  
  // 初始化终端（如果未初始化）
  public async initTerminal(serverIp: string, container: HTMLElement): Promise<boolean> {
    const connection = this.getConnection(serverIp)
    
    // 如果已经初始化，只需要更新容器引用
    if (connection.initialized && connection.terminal && connection.container) {
      const terminalContainer = connection.container
      
      // 如果容器已经附加到目标位置，不需要重新初始化
      if (terminalContainer.parentElement === container) {
        return true
      }
      
      // 将现有的终端容器移动到新位置
      if (terminalContainer.parentElement) {
        terminalContainer.parentElement.removeChild(terminalContainer)
      }
      
      container.innerHTML = ''
      container.appendChild(terminalContainer)
      
      // 重新附加resize observer（观察终端容器）
      if (connection.resizeObserver) {
        connection.resizeObserver.disconnect()
      }
      connection.resizeObserver = new ResizeObserver(() => {
        connection.fitAddon?.fit()
      })
      connection.resizeObserver.observe(terminalContainer)
      
      await new Promise(resolve => setTimeout(resolve, 50))
      connection.fitAddon?.fit()
      connection.terminal?.focus()
      return true
    }
    
    // 创建新的终端实例
    try {
      const terminal = new Terminal({
        cursorBlink: true,
        fontSize: 12,
        fontFamily: 'Menlo, Monaco, Consolas, "Courier New", monospace',
        disableStdin: false,
        theme: { background: '#ffffff', foreground: '#111827', cursor: '#4b5563' }
      })
      
      const fitAddon = new FitAddon()
      terminal.loadAddon(fitAddon)
      
      const terminalContainer = document.createElement('div')
      terminalContainer.className = 'webssh-terminal-container'
      terminalContainer.style.width = '100%'
      terminalContainer.style.height = '100%'
      
      container.innerHTML = ''
      container.appendChild(terminalContainer)
      terminal.open(terminalContainer)
      fitAddon.fit()
      
      const resizeObserver = new ResizeObserver(() => {
        fitAddon.fit()
      })
      resizeObserver.observe(terminalContainer)
      
      connection.terminal = terminal
      connection.fitAddon = fitAddon
      connection.container = terminalContainer
      connection.initialized = true
      connection.resizeObserver = resizeObserver
      
      terminal.focus()
      return true
    } catch (err) {
      console.error(`WebSSH终端初始化失败 (${serverIp}):`, err)
      return false
    }
  }
  
  // 连接WebSSH
  public connect(serverIp: string): void {
    const connection = this.getConnection(serverIp)
    if (!connection.terminal) {
      console.error(`[WebSSH管理器] 终端未初始化，无法连接 ${serverIp}`)
      return
    }
    
    // 如果已经连接，先断开
    if (connection.socket) {
      this.disconnect(serverIp)
    }
    
    connection.status = 'connecting'
    
    try {
      const wsUrl = `/webssh?ip=${encodeURIComponent(serverIp)}`
      const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'
      const fullWsUrl = `${protocol}//${window.location.host}${wsUrl}`
      const socket = new WebSocket(fullWsUrl)
      
      socket.onopen = () => {
        connection.status = 'connected'
        connection.socket = socket
        const dataHandler = (data: string) => {
          if (socket.readyState === WebSocket.OPEN) {
            socket.send(data)
          }
        }
        connection.dataHandler = dataHandler
        connection.terminal?.onData(dataHandler)
        setTimeout(() => connection.terminal?.focus(), 100)
        console.log(`[WebSSH管理器] 已连接到 ${serverIp}`)
      }
      
      let firstMessageReceived = false
      socket.onmessage = event => {
        if (!firstMessageReceived) {
          try {
            const data = JSON.parse(event.data)
            if (data.status === 'connected') {
              connection.terminal?.writeln(`\r\n${data.message || 'SSH连接成功。'}\r\n`)
              firstMessageReceived = true
              return
            }
            if (data.error) {
              connection.terminal?.writeln(`\r\n错误: ${data.error}\r\n`)
              connection.status = 'error'
              socket.close()
              return
            }
          } catch {
            firstMessageReceived = true
          }
        }
        if (firstMessageReceived && connection.terminal) {
          connection.terminal.write(event.data)
        }
      }
      
      socket.onerror = () => {
        connection.status = 'error'
        connection.terminal?.writeln('\r\n连接错误，请检查网络和服务器配置。\r\n')
        console.error(`[WebSSH管理器] 连接错误 ${serverIp}`)
      }
      
      socket.onclose = event => {
        // 只有在非主动断开的情况下才更新状态
        if (connection.status !== 'disconnected') {
          connection.status = 'disconnected'
          connection.terminal?.writeln(`\r\n连接已断开。代码: ${event.code}\r\n`)
        }
        connection.socket = null
        console.log(`[WebSSH管理器] 连接已断开 ${serverIp}, 代码: ${event.code}`)
      }
    } catch (err) {
      connection.status = 'error'
      connection.terminal?.writeln(`\r\n连接失败: ${err instanceof Error ? err.message : '未知错误'}\r\n`)
      console.error(`[WebSSH管理器] 连接失败 ${serverIp}:`, err)
    }
  }
  
  // 断开连接（但保持终端实例）
  public disconnect(serverIp: string): void {
    const connection = this.getConnection(serverIp)
    if (connection.socket) {
      connection.socket.close()
      connection.socket = null
    }
    connection.status = 'disconnected'
    connection.dataHandler = null
    console.log(`[WebSSH管理器] 已断开连接 ${serverIp}`)
  }
  
  // 获取连接状态
  public getStatus(serverIp: string): WebSSHConnection['status'] {
    return this.getConnection(serverIp).status
  }
  
  // 清理终端容器（组件卸载时调用，但不断开WebSocket）
  public detachContainer(serverIp: string): void {
    const connection = this.getConnection(serverIp)
    // 只清理容器引用，不断开WebSocket连接
    // 这样连接可以在后台保持
    if (connection.container && connection.container.parentElement) {
      // 不删除容器，只是从DOM中移除
      // 但保留引用以便重新附加
    }
  }
  
  // 重新附加容器（组件重新挂载时调用）
  public async reattachContainer(serverIp: string, newContainer: HTMLElement): Promise<void> {
    const connection = this.getConnection(serverIp)
    if (connection.initialized && connection.container) {
      // 将现有的终端容器移动到新的父容器中
      const terminalContainer = connection.container
      
      // 如果终端容器已经在DOM中，先从原位置移除
      if (terminalContainer.parentElement) {
        terminalContainer.parentElement.removeChild(terminalContainer)
      }
      
      // 将终端容器附加到新位置
      newContainer.innerHTML = ''
      newContainer.appendChild(terminalContainer)
      
      // 重新附加resize observer（观察终端容器，而不是父容器）
      if (connection.resizeObserver) {
        connection.resizeObserver.disconnect()
      }
      connection.resizeObserver = new ResizeObserver(() => {
        connection.fitAddon?.fit()
      })
      connection.resizeObserver.observe(terminalContainer)
      
      await new Promise(resolve => setTimeout(resolve, 50))
      connection.fitAddon?.fit()
      connection.terminal?.focus()
    } else {
      // 如果未初始化，初始化终端
      await this.initTerminal(serverIp, newContainer)
    }
  }
  
  // 清空终端内容
  public clear(serverIp: string): void {
    const connection = this.getConnection(serverIp)
    connection.terminal?.clear()
    setTimeout(() => connection.terminal?.focus(), 50)
  }
}

// 全局单例实例
let globalWebSSHManager: WebSSHManager | null = null

// 导出composable函数
export function useWebSSH() {
  if (!globalWebSSHManager) {
    globalWebSSHManager = new WebSSHManager()
  }
  
  return {
    getConnection: (serverIp: string) => globalWebSSHManager!.getConnection(serverIp),
    getAllConnections: () => globalWebSSHManager!.getAllConnections(),
    setServers: (servers: WebSSHServer[]) => globalWebSSHManager!.setServers(servers),
    getServers: () => globalWebSSHManager!.getServers(),
    initTerminal: (serverIp: string, container: HTMLElement) => globalWebSSHManager!.initTerminal(serverIp, container),
    connect: (serverIp: string) => globalWebSSHManager!.connect(serverIp),
    disconnect: (serverIp: string) => globalWebSSHManager!.disconnect(serverIp),
    getStatus: (serverIp: string) => globalWebSSHManager!.getStatus(serverIp),
    detachContainer: (serverIp: string) => globalWebSSHManager!.detachContainer(serverIp),
    reattachContainer: (serverIp: string, container: HTMLElement) => globalWebSSHManager!.reattachContainer(serverIp, container),
    clear: (serverIp: string) => globalWebSSHManager!.clear(serverIp)
  }
}

